import { app, BrowserWindow, dialog, ipcMain, shell } from "electron";

import SystemManager, { isProduction } from "./core/systemManager"
import { ChildProcess, fork } from "child_process";
import { errorMsg } from "~/types/interface.node";
import _conf from "@conf/default.json";
import { MainLogger } from "./utils/logs";
import { sep } from "path";
import VideoTransferManager from "./core/videoTransferManager";
import BrowserViewManager from "./core/browerviewManager";
import DownloadManager from "./core/downloadManager";
import ChatManager from "./core/chatgptManager";
import YoutubeManager from "./core/youtubeManager";
import FileManager, { isExist, joinFilePath } from "./core/fileManager";
import ProcessManager from "./core/processManager";
import CaptureManager from "./core/captureManager";
import PuppeteerManager from "./core/puppeteer";



class AppManager {

    public appTitle: string;
    private downloadEventMap: Record<string, Function>

    constructor(appTitle: string) {
        this.appTitle = appTitle;

        // 开启日志处理
        this.setupLogMiddleware();
        // 创建系统
        this.init();

        // 注册通信事件
        this.registerIpcEvent();
        this.registerAppEvent();
        this.registerSystemEvent();

        // ！todo 下载事件Map
        this.downloadEventMap = {
            'download-start': (event: Electron.IpcMainInvokeEvent, e: { id: string, mu: string, fn: string }) => {
                DownloadManager.getInstance().init(e.id.toString(), e.mu, e.fn);
            },
            'download-pause': () => DownloadManager.getInstance().pauseTask(),
            'check-is-exist': (event: Electron.IpcMainInvokeEvent, data: { fr: string, nm: string, cd: string, ou: string }) => {
                DownloadManager.getInstance().checkIsExist(event, data);
            },
            'request-range': (event: Electron.IpcMainInvokeEvent, data: { tm: string | object, ou: string }) => {
                console.log('啥呀哈哈哈', data);
                DownloadManager.getInstance().getVideoText(data.tm, data.ou);
            },
            'confirm-delete': (event: Electron.IpcMainInvokeEvent, data: string) => {
                console.log('删除的id', data);
                DownloadManager.getInstance().deleteById(data, event);
            },
            'update-time': (event: Electron.IpcMainInvokeEvent, data: string) => {
                SystemManager.getInstance().sendMessageToRender('update-time', data);
                console.log('更新了恶魔', data)
            },
            'update-mutxt': () => {

            }
        }

        process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
    }



    init() {

        app.whenReady().then(() => {
            Promise.all([
                SystemManager.getInstance().createMainWindow(this.appTitle),
                isProduction && ProcessManager.getInstance().startVideoSever()
            ])
        })
    }

    registerIpcEvent() {
        // 创建视频播放子窗口
        ipcMain.handle("createChildWindow", (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { name, conf }: { name: "player" | "other", conf: PlayerWindowConf } = JSON.parse(data);
            name == "player" && SystemManager.getInstance().createPlayWindow(conf);
        })

        // 本地连接远端视频
        ipcMain.handle("remoteVideo", () => { })

        ipcMain.handle('addContext', (event: Electron.IpcMainInvokeEvent, data: string) => {
            // console.log(JSON.parse(data), 'ADDD');
            const video: NavCoverItem = JSON.parse(data)
            SystemManager.getInstance().addContextMenu(video);
        })

        // 保存前检测
        ipcMain.handle('checkBeforeSave', (event: Electron.IpcMainInvokeEvent) => {
            SystemManager.getInstance().sendMessageToRender('checkBeforeSave', undefined);
        })

        ipcMain.handle('HandleBrowserView', (event: Electron.IpcMainInvokeEvent, data: string) => {
            JSON.parse(data)?.k ? BrowserViewManager.getInstance().init() : BrowserViewManager.getInstance().hideProxyPage();
        })


        ipcMain.handle('openDesignatedShell', (event: Electron.IpcMainInvokeEvent, data: string) => {
            let { eventName, url } = JSON.parse(data);
            url = url.replaceAll('"', '').replaceAll("\\\\", "\\")
            eventName = eventName || 'openDirectly'
            const handle = {
                openDirectly() {
                    url && isExist(url) && shell.openPath(url);
                },
                openJsFolder() {
                    url = joinFilePath(FileManager.getInstance().getRelevantPath('sp'), url);
                    url && isExist(url) && shell.openPath(url);
                },
                openVideoPath() {
                    url && isExist(url) && shell.openPath(url);
                }
            }
            handle[eventName] && handle[eventName]()
        })

        // 视频转换操作
        ipcMain.handle('convertHandle', (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { name, val } = JSON.parse(data);
            const handle = {
                init() { },
                // 选择文件
                openFile() {
                    dialog.showOpenDialog({
                        buttonLabel: "请选择",
                        filters: [{ extensions: ['mp4', 'flv', 'mlv'], name: '' }],
                        properties: ["openFile"] //支持文件操作方式,多选("multiSelections",),单选,打开文件,打开文件夹,创建文件
                    }).then((res) => {
                        if (res.canceled === true || !res.filePaths.length) return;
                        const filePath = res.filePaths.pop() || '';
                        const name = filePath?.split(sep).pop() || '';
                        const isExist = VideoTransferManager.getInstance().checkIsExist(name)
                        isExist ? SystemManager.getInstance().sendMessageToRender('initVideoParams', isExist) : VideoTransferManager.getInstance().initTaskBeforeCreate({
                            origin: filePath,
                            output: FileManager.getInstance().getCompressOut(name),
                            name
                        })
                    })
                },
                // 选择文件夹
                openMultiFiles() {
                    dialog.showOpenDialog({
                        buttonLabel: "请选择",
                        properties: ["openDirectory"]
                    }).then(res => {
                        if (res.canceled === true || !res.filePaths.length) return;
                        console.log(res.filePaths)
                        const folderPath = res.filePaths.pop() || '';
                        VideoTransferManager.getInstance().scanFolder(folderPath)
                    })
                },
                // 开始转换单个
                startConvert() {
                    const { name, conf } = val as { name: string, conf: TransferVideoOption }
                    VideoTransferManager.getInstance().startTransferTask(name, conf);
                },
                // 开始转换多个
                startMultiTask() {
                    VideoTransferManager.getInstance().startMultiTask();
                },
                // 打开输出文件夹
                openOutFolder() {
                    shell.openPath(FileManager.getInstance().getCompressOut(''));
                },
                // 更新转换配置
                updateConf() {
                    const { name, conf } = val as { name: string, conf: RCDD }
                    VideoTransferManager.getInstance().updateConf(name, conf)
                }
            }

            handle[name] && handle[name]();
        })

        // m3u8下载处理
        ipcMain.handle('downloadHandle', (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { eventName, conf }: { eventName: string, conf: any } = JSON.parse(data);
            Object.keys(this.downloadEventMap).forEach(key => {
                eventName === key && this.downloadEventMap[key](event, conf);
            })
        })

        // youtube下载
        ipcMain.handle('youtubeHandle', (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { conf, eventName } = JSON.parse(data);
            const obj = {
                analysisUrl() {
                    YoutubeManager.getInstance().readInfoByUrl(conf)
                },
                startDownload() {
                    YoutubeManager.getInstance().startDownload(conf);
                }
            }
            obj[eventName] && obj[eventName]()
        })

        // 录制视频事件操作
        ipcMain.handle('recordEvent', (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { type }: { type: 'area' | 'window' | 'fullscreen' | 'stop' } = JSON.parse(data) || {};
            switch (type) {
                case "area": {
                    CaptureManager.getInstance().startAreaCapture();
                    return;
                }
                case 'fullscreen': {
                    CaptureManager.getInstance().startFullCapture();
                    return;
                }
                case 'window': {
                    CaptureManager.getInstance().startAppCapture();
                    return;
                }
                case "stop": {
                    CaptureManager.getInstance().stopCaptureProcess();
                    return;
                }
            }
        })


        ipcMain.handle('openShell', (event: Electron.IpcMainInvokeEvent, data: string) => {
            console.log('打开的路径', data);
            FileManager.getInstance().openRelevantShell(data);
        })

        // !todo
        ipcMain.handle('processHandle', (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { eventName, conf }: { eventName: string, conf: any } = JSON.parse(data);
            console.log(eventName, conf)
        })

        ipcMain.handle('crawlerEvent', (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { tag, _data }: { tag: "start" | 'stop' | 'pause', _data?: CrawlerInitConf } = JSON.parse(data);
            switch (tag) {
                case "start": {
                    PuppeteerManager.getInstance().init(_data);
                    return;
                }
                case "pause": {

                    return;
                }
                case "stop": {
                    PuppeteerManager.getInstance().stopTask();
                    return
                }
            }
        })
    }

    // 处理app配置相关的api
    registerSystemEvent() {

        // 系统文件配置文件
        ipcMain.handle('initSysConf', () => {
            FileManager.getInstance().initSysConf()
        })

        ipcMain.handle('systemSetting', (event: Electron.IpcMainInvokeEvent, data: string) => {
            const { key, value }: { key: keyof AppSetting, value: any } = JSON.parse(data);
            // console.log(key, value);
            const handle: Record<keyof MyAppSetting, Function> = {
                'ap': function () {
                    FileManager.getInstance().updateSysSetting({ 'ap': value })
                },
                'lp': function () {
                    FileManager.getInstance().updateSysSetting({ 'lp': value })
                },
                'apiUrl': function () {
                    FileManager.getInstance().updateSysSetting({ 'apiUrl': value })
                },
                'apiKey': function () {
                    FileManager.getInstance().updateSysSetting({ 'apiKey': value })
                },
                'sp': function () {
                    console.log('打开配置');
                    dialog.showOpenDialog({
                        defaultPath: joinFilePath(FileManager.getInstance().getRelevantPath('sp'), '..'),
                        properties: ['openDirectory']
                    }).then(res => {
                        const { filePaths: [p], canceled } = res;
                        if (canceled) return;
                        FileManager.getInstance().updateSysSetting({ 'sp': p })
                    })
                },
                'op': function () {
                    console.log('打开配置');
                    dialog.showOpenDialog({
                        defaultPath: joinFilePath(FileManager.getInstance().getRelevantPath('op'), '..'),
                        properties: ['openDirectory']
                    }).then(res => {
                        const { filePaths: [p], canceled } = res;
                        if (canceled) return;
                        FileManager.getInstance().updateSysSetting({ 'op': p })
                    })
                },
                'cs': function () {
                    SystemManager.getInstance().setShutDownCount(value);
                    FileManager.getInstance().updateSysSetting({ 'cs': value })
                },
                'compress': function () {
                    dialog.showOpenDialog({
                        defaultPath: joinFilePath(FileManager.getInstance().getRelevantPath('compress'), '..'),
                        properties: ['openDirectory']
                    }).then(res => {
                        const { filePaths: [p], canceled } = res;
                        if (canceled) return;
                        FileManager.getInstance().updateSysSetting({ 'compress': p })
                    })
                },
                'workerTotal': function () {
                    FileManager.getInstance().updateSysSetting({ 'workerTotal': value })
                },
                'yt': function () {

                }
            }
            handle[key] && handle[key]();
        })
    }


    // 系统内置的事件
    registerAppEvent() {
        app.on('activate', () => {
            const allWindows = BrowserWindow.getAllWindows()
            if (allWindows.length) {
                allWindows[0].focus()
            } else {
                SystemManager.getInstance().createMainWindow(this.appTitle);
            }
        })

        app.on('before-quit', () => {
            ProcessManager.getInstance().offlineVideoSever();

        })

        app.on('window-all-closed', () => SystemManager.getInstance().quitSystem())
    }

    // 日志处理
    setupLogMiddleware() {
        process.on("uncaughtException", function (errInfo: Error, origin: NodeJS.UncaughtExceptionOrigin) {
            let sendMsg: errorMsg = {
                type: "jsError",
                message: String(errInfo),
                origin,
                stack: errInfo?.stack?.split("\n").at(1)?.split(FileManager.getInstance().getProjectPath()).pop() || "",
                name: errInfo.name,
                time: new Date().toLocaleString(),

            }
            console.log(sendMsg, '主进程');
            // electronApp.handleError(sendMsg);
            MainLogger.error(JSON.stringify(sendMsg));

        })

        process.on("unhandledRejection", function (reason: Error, origin: any) {
            console.log("handle rejection", ...arguments);
            let sendMsg: errorMsg = {
                type: "rejectionError",
                message: String(reason),
                origin,
                stack: reason?.stack?.split("\n").at(1)?.split(FileManager.getInstance().getProjectPath()).pop() || "",
                name: reason.name,
                time: new Date().toLocaleString(),

            }
            console.log(sendMsg, '异步进程');
            MainLogger.error(JSON.stringify(sendMsg));

            // SystemManager.getInstance().win?.webContents.send("errorHandler", sendMsg);
        })

        process.on('SIGINT', () => {
            console.log('视频的取消了呢')
            ProcessManager.getInstance().offlineVideoSever();
        })

        process.on('exit', () => {
            ProcessManager.getInstance().offlineVideoSever();
        })
    }

    handleError(msg: errorMsg) {
        SystemManager.getInstance().win?.webContents.send("errorHandler", msg);
    }
}


new AppManager(_conf.title);

